From: Keir Fraser Date: Fri, 17 Apr 2009 12:14:01 +0000 (+0100) Subject: cpuidle: Add support for Always Running APIC timer, CPUID_0x6_EAX_Bit2. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13970 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22?a=commitdiff_plain;h=ede78f509c7f2b79d741e450bfca7b8d4a262b94;p=xen.git cpuidle: Add support for Always Running APIC timer, CPUID_0x6_EAX_Bit2. This bit means the APIC timer continues to run even when CPU is in deep C-states. The advantage is that we can use LAPIC timer on these CPUs always, and there is no need for "slow to read and program" external timers (HPET/PIT) and the timer broadcast logic and related code in C-state entry and exit. Refer to the latest Intel SDM Vol 2A (http://www.intel.com/products/processor/manuals/index.htm) Signed-off-by: Wei Gang --- diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c index b302f15a7c..0685194029 100644 --- a/xen/arch/x86/acpi/cpu_idle.c +++ b/xen/arch/x86/acpi/cpu_idle.c @@ -51,6 +51,7 @@ /*#define DEBUG_PM_CX*/ +static void lapic_timer_nop(void) { } static void (*lapic_timer_off)(void); static void (*lapic_timer_on)(void); @@ -538,8 +539,12 @@ static int check_cx(struct acpi_processor_power *power, xen_processor_cx_t *cx) if ( local_apic_timer_c2_ok ) break; case ACPI_STATE_C3: - /* We must be able to use HPET in place of LAPIC timers. */ - if ( hpet_broadcast_is_available() ) + if ( boot_cpu_has(X86_FEATURE_ARAT) ) + { + lapic_timer_off = lapic_timer_nop; + lapic_timer_on = lapic_timer_nop; + } + else if ( hpet_broadcast_is_available() ) { lapic_timer_off = hpet_broadcast_enter; lapic_timer_on = hpet_broadcast_exit; diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c index 1574004f6c..4715f3438c 100644 --- a/xen/arch/x86/cpu/intel.c +++ b/xen/arch/x86/cpu/intel.c @@ -222,6 +222,9 @@ static void __devinit init_intel(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); set_bit(X86_FEATURE_NOSTOP_TSC, c->x86_capability); } + if ((c->cpuid_level >= 0x00000006) && + (cpuid_eax(0x00000006) & (1u<<2))) + set_bit(X86_FEATURE_ARAT, c->x86_capability); start_vmx(); } diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index b44871e139..9e9ff9b456 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -1274,7 +1274,7 @@ static int disable_pit_irq(void) * XXX dom0 may rely on RTC interrupt delivery, so only enable * hpet_broadcast if FSB mode available or if force_hpet_broadcast. */ - if ( xen_cpuidle ) + if ( xen_cpuidle && !boot_cpu_has(X86_FEATURE_ARAT) ) { hpet_broadcast_init(); if ( !hpet_broadcast_is_available() ) diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index 4c6eeabc55..f36d7070c0 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -75,6 +75,7 @@ #define X86_FEATURE_P4 (3*32+ 7) /* P4 */ #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ #define X86_FEATURE_NOSTOP_TSC (3*32+ 9) /* TSC does not stop in C states */ +#define X86_FEATURE_ARAT (3*32+ 10) /* Always running APIC timer */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */